feat: Add UI button to copy direct message links#13103
Conversation
b56e414 to
ed6ac73
Compare
📝 WalkthroughWalkthroughThe 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/MenuEnvelope.vue (1)
1-4:⚠️ Potential issue | 🟠 Major | ⚡ Quick winUpdate SPDX header to the required repository format
This
.vuefile header does not match the mandated SPDX header template for touched JS/Vue files.As per coding guidelines, "
**/*.{php,js,ts,tsx,vue}: Every file must include an SPDX license header. ... Header format: /* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */".Source: Coding guidelines
🧹 Nitpick comments (1)
src/components/MenuEnvelope.vue (1)
667-670: ⚡ Quick winDe-duplicate/reset the copy-state timeout
Repeated clicks enqueue multiple timers, which can cause stale state flips and inconsistent menu-close timing.
Proposed refactor
data() { return { + copyResetTimer: null, copied: false, } }, ... finally { + if (this.copyResetTimer) { + clearTimeout(this.copyResetTimer) + } - setTimeout(() => { + this.copyResetTimer = setTimeout(() => { this.copied = false this.localMoreActionsOpen = false + this.copyResetTimer = null }, 2000) }
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 779cf0e3-cfcd-478f-938a-ca84d05cee6e
📒 Files selected for processing (1)
src/components/MenuEnvelope.vue
| const trimmedMessageId = this.envelope.messageId.trim().replace(/^<|>$/g, '') | ||
| const url = window.location.origin + generateUrl('/apps/mail/open/' + encodeURIComponent(trimmedMessageId)) |
There was a problem hiding this comment.
Guard messageId before calling trim()
Line 655 can throw when this.envelope.messageId is missing/null, which breaks the action instead of falling back gracefully.
Proposed fix
async onCopyMessageLink() {
- const trimmedMessageId = this.envelope.messageId.trim().replace(/^<|>$/g, '')
+ const rawMessageId = this.envelope?.messageId
+ if (typeof rawMessageId !== 'string' || rawMessageId.trim() === '') {
+ showError(t('mail', 'Could not generate direct link for this message'))
+ return
+ }
+ const trimmedMessageId = rawMessageId.trim().replace(/^<|>$/g, '')
const url = window.location.origin + generateUrl('/apps/mail/open/' + encodeURIComponent(trimmedMessageId))📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const trimmedMessageId = this.envelope.messageId.trim().replace(/^<|>$/g, '') | |
| const url = window.location.origin + generateUrl('/apps/mail/open/' + encodeURIComponent(trimmedMessageId)) | |
| async onCopyMessageLink() { | |
| const rawMessageId = this.envelope?.messageId | |
| if (typeof rawMessageId !== 'string' || rawMessageId.trim() === '') { | |
| showError(t('mail', 'Could not generate direct link for this message')) | |
| return | |
| } | |
| const trimmedMessageId = rawMessageId.trim().replace(/^<|>$/g, '') | |
| const url = window.location.origin + generateUrl('/apps/mail/open/' + encodeURIComponent(trimmedMessageId)) |
Implements a UI button in the MenuEnvelope to generate and copy a direct link to the message using the new deep link route. Utilizes the standard Nextcloud clipboard fallback via window.prompt for non-secure contexts. Signed-off-by: SoleroTG <github-29h@solero.quietmail.eu>
ed6ac73 to
62b0de7
Compare
This PR provides the frontend UI implementation for message-id deep links, completing the foundational work established in #12632 and the CSRF fix in #12959.
It adds a new action button to the
MenuEnvelopecomponent (the "More actions" menu on a message) to easily copy the generated link.Key implementations:
navigator.clipboard.writeText()for a seamless user experience in secure contexts.showSuccess) is triggered, and the menu icon temporarily changes to a checkmark before the menu closes.window.prompt. This directly mirrors the fallback behavior established in@nextcloud/vue'suseCopycomposable.Resolves #2269
To Test:
...) on any message to open the actions menu.